home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 26 / CU Amiga Magazine's Super CD-ROM 26 (1998)(EMAP Images)(GB)[!][issue 1998-09].iso / CDSupport / ClassAct / AmigaE / LayoutExample.e < prev    next >
Text File  |  1997-07-09  |  21KB  |  532 lines

  1. /*************************************************************************
  2.  * ClassAct Comprehensive Demo Program
  3.  * Copyright © 1995 Phantom Development Co.
  4.  *
  5.  * Translated from C to E by Eric Sauvageau.
  6.  */
  7.  
  8.  
  9. /*
  10. Supply inithook.m with ClassAct?  Or at least its source?  Might be added
  11.   to  classact_lib.m?
  12.  
  13. */
  14.  
  15. OPT PREPROCESS
  16.  
  17. MODULE 'tools/constructors'
  18. MODULE 'tools/boopsi','tools/installhook','tools/inithook'
  19.  
  20. MODULE 'exec/types','exec/memory','intuition/intuition','exec/ports',
  21.        'intuition/gadgetclass','intuition/icclass','libraries/gadtools',
  22.        'graphics/gfxbase','graphics/text','graphics/gfxmacros',
  23.        'utility/tagitem','workbench/startup','workbench/workbench',
  24.        'intuition','graphics','exec','dos','diskfont','utility','wb','icon',
  25.        'utility/hooks','intuition/classes','intuition/classusr',
  26.        'exec/lists','exec/nodes','dos/rdargs','dos/dos'
  27.  
  28.  
  29. MODULE 'classes/window','gadgets/listbrowser','listbrowser',
  30.        'other/classact_macros','layout','gadgets/layout','images/bevel',
  31.        'gadgets/chooser','chooser','images/label','label','window',
  32.        'button'
  33.  
  34. MODULE 'tools/classact_lib'
  35.  
  36. /* a simple button */
  37. #define Button(a) ButtonObject, GA_TEXT, a, ButtonEnd
  38. #define DButton(a) ButtonObject, GA_TEXT, a, GA_DISABLED, TRUE, ButtonEnd
  39.  
  40.  
  41. /**************************************************************************
  42.  * Some label arrays for the gadgets in this demo.
  43.  */
  44.  
  45. DEF objtypes:PTR TO LONG,
  46.     objnames:PTR TO LONG
  47.  
  48.  
  49. /*************************************************************************
  50.  * ReadArgs
  51.  */
  52.  
  53. #define TEMPLATE 'S=SIMPLEREFRESH/S,NC=NOCAREREFRESH/S,ND=NDEFER/S'
  54.  
  55. ENUM A_SIMPLE, A_NOCARE, A_NODEFER
  56.  
  57. DEF arguments:PTR TO LONG
  58.  
  59.  
  60. -> Must use separate vars because for some reason, EC chokes when you try
  61. -> to assign a value to an indexed array in the middle of a list...  Will
  62. -> have to notify Wouter about that bugger.
  63. -> We will manualy build the list later.
  64.  
  65. ENUM G_OBJTYPE=1, G_OBJLIST, G_TOP, G_UP, G_DOWN, G_BOTTOM, G_SORT,
  66.      G_NEW, G_EDIT, G_COPY, G_REMOVE, G_HELP, G_SAVE, G_USE, G_TEST,
  67.      G_CANCEL,G_END
  68.  
  69. DEF gl[18]: ARRAY OF LONG
  70.  
  71. DEF g_objtype,
  72.     g_objlist,
  73.     g_top,
  74.     g_up,
  75.     g_down,
  76.     g_bottom,
  77.     g_sort,
  78.     g_new,
  79.     g_edit,
  80.     g_copy,
  81.     g_remove,
  82.     g_help,
  83.     g_save,
  84.     g_use,
  85.     g_test,
  86.     g_cancel
  87.  
  88.  
  89. PROC init()
  90.    objtypes:=['Exec','Image','Sound','Menu','Icon','Dock','Access',NIL]
  91.    objnames:=['ToolManager','ScreenMode','WBPattern',NIL]
  92.  
  93.    buttonbase :=openClass('gadgets/button.gadget',0)
  94.    listbrowserbase :=openClass('gadgets/listbrowser.gadget',0)
  95.    chooserbase :=openClass('gadgets/chooser.gadget',0)
  96.    windowbase :=openClass('window.class',0)
  97.    layoutbase :=openClass('gadgets/layout.gadget',0)
  98.    labelbase := openClass('images/label.image',0)
  99.  
  100.    iconbase := OpenLibrary('icon.library',36)
  101.  
  102. ENDPROC
  103.  
  104.  
  105. /*************************************************************************
  106.  * App message hook.
  107.  * Workbench App messages can be caught with a callback hook such as this.
  108.  * We'll not worry about the app message type in this hook. Objects dropped
  109.  * on the window or on the icon (while iconified) will be added to the 
  110.  * listview.
  111.  */
  112.  
  113.  
  114. PROC appMsgFunc(hook:PTR TO hook, window:PTR TO object, msg:PTR TO appmessage)
  115. DEF win: PTR TO window, i, arg:PTR TO wbarg, l: PTR TO lh, n:PTR TO ln,
  116.     name[256]:STRING
  117.  
  118.    i := msg.numargs
  119.    arg := msg.arglist
  120.    l := hook.data
  121.  
  122.    GetAttr(WINDOW_WINDOW, window, {win} )
  123.  
  124.  
  125. -> Detach the list for modifications.
  126.  
  127.    SetGadgetAttrsA(g_objlist, win, NIL,[LISTBROWSER_LABELS, Not(0), TAG_END])
  128.         
  129.    WHILE i
  130.       /* Add the name of the icon to the listview. ListBrowser can copy the
  131.        * text into an internal buffer and thus let us not worry about the
  132.        * pointer validity.
  133.        */
  134.  
  135.       DEC i
  136.  
  137.       NameFromLock(arg.lock, name, 256)
  138.       AddPart(name,arg.name, 256)
  139.  
  140.       IF (n := AllocListBrowserNodeA(1, [LBNCA_COPYTEXT, TRUE, LBNCA_TEXT, name, TAG_END])) THEN AddTail(l, n)
  141.  
  142.       arg++
  143.  
  144.    ENDWHILE
  145.  
  146. -> Reattach the list
  147.  
  148.    SetGadgetAttrsA(g_objlist, win, NIL, [LISTBROWSER_LABELS, l, TAG_END])
  149. ENDPROC
  150.  
  151.  
  152. /*************************************************************************
  153.  * Main Program
  154.  */
  155.  
  156. PROC main() HANDLE
  157. DEF objlist=NIL:PTR TO lh,
  158.     typelist:PTR TO lh,
  159.     args=NIL:PTR TO rdargs,
  160.     appport: PTR TO mp,
  161.     window=NIL:PTR TO object,
  162.     mainlayout:PTR TO window,
  163.     apphook:hook,
  164.     win:PTR TO window,
  165.     wsig, asig,done=FALSE,
  166.     sig,result,code,
  167.     tmp,tmp2,tmp3,
  168.     ids:PTR TO LONG,
  169.     dis=FALSE,i,
  170.     helptext[40]:STRING
  171.  
  172.  
  173. -> Init some lists, and open the required gadgets/libraries.
  174.  
  175. init()
  176.  
  177. ids := [G_TOP, G_UP, G_DOWN, G_BOTTOM, G_EDIT, G_COPY, G_REMOVE, G_END ]
  178.  
  179. arguments:=[0,0,0]
  180. IF (args := ReadArgs(TEMPLATE, arguments, NIL))=NIL THEN Raise(20)
  181.  
  182.  
  183. IF ((iconbase<>NIL) AND (buttonbase<>NIL) AND (listbrowserbase<>NIL) AND (chooserbase<>NIL) AND (windowbase<>NIL) AND (layoutbase<>NIL) AND (labelbase<>NIL))
  184.  
  185.    WriteF('\seferred \s refresh \s\n', (IF arguments[A_NODEFER] THEN 'Non-d' ELSE 'D'), (IF arguments[A_SIMPLE] THEN 'Simple' ELSE 'Smart'), (IF arguments[A_NOCARE] THEN '(NoCare)' ELSE ''))
  186.  
  187.    objlist := browserNodesA(objnames)
  188.    typelist := chooserLabelsA(objtypes)
  189.  
  190.    /* By providing a message port you enable windowclass to handle iconification
  191.     * and appwindows. This port can shared by all the windows of your application.
  192.     */
  193.  
  194.    appport := CreateMsgPort()
  195.  
  196.    IF (objlist AND typelist AND appport)
  197.       inithook(apphook,{appMsgFunc},objlist)
  198.  
  199.       /* Create a Window object with a Layout. When Window is asked to open itself,
  200.        * it will calculate how much space the Layout needs and size itself accordingly.
  201.        */
  202.  
  203.  
  204.       window := WindowObject,
  205.                    WA_IDCMP, IDCMP_RAWKEY,
  206.                    WA_TOP, 20,
  207.                    WA_LEFT, 20,
  208.                    WA_SIZEGADGET, TRUE,
  209.                    WA_DEPTHGADGET, TRUE,
  210.                    WA_DRAGBAR, TRUE,
  211.                    WA_CLOSEGADGET, TRUE,
  212.                    WA_ACTIVATE, TRUE,
  213.  
  214.                    /* About window refreshes:
  215.                     * Because WindowClass and LayoutClass can, when used together, change the
  216.                     * normal Intuition practise of refreshing gadgets in the input.device context,
  217.                     * some rules about the refresh system change.
  218.                     * Deferred refresh works in both smart and simple refresh windows, but
  219.                     * if nocarerefresh is used, Intuition does not retain the damage regions
  220.                     * and any window damage will force the whole window to be refreshed.
  221.                     * This demo allows you to try combinations of refresh types.
  222.                     * In the normal case you can ignore this and let WindowClass and the user
  223.                     * decide what kind of refreshes they want. Nocare refresh can be
  224.                     * combined with smart refresh to provide a fast, but somewhat more memory
  225.                     * hungry refresh method. Simple refresh can save some memory but it's
  226.                     * slower.
  227.                     */
  228.  
  229.                    WA_SIMPLEREFRESH, arguments[A_SIMPLE],
  230.                    WA_NOCAREREFRESH, arguments[A_NOCARE],    
  231.                    WA_SMARTREFRESH, Not(arguments[A_SIMPLE]),
  232.                 
  233.                    WA_TITLE, 'ClassAct layout.gadget Example (ToolManager preferences mockup)',
  234.                    WA_SCREENTITLE, 'ClassAct Copyright 1995 Phantom Development LLC.',
  235.                 
  236.                    /* Turn on gadget help in the window 
  237.                     */
  238.                 
  239.                    WINDOW_GADGETHELP, TRUE,
  240.                 
  241.                    /* Add an iconification gadget. If you have this, you must listen to
  242.                     * WMHI_ICONIFY.
  243.                     */
  244.                  
  245.                    WINDOW_ICONIFYGADGET, TRUE,
  246.     
  247.                    /* This message port lets windowclass handle the icon and appwindow.
  248.                     */
  249.                  
  250.                    WINDOW_APPPORT, appport,
  251.                    WINDOW_APPWINDOW, TRUE,
  252.                    WINDOW_APPMSGHOOK, apphook,
  253.                 
  254.                    /* The windowclass will automatically free the DiskObject used when
  255.                     * iconifying the window. If you do not provide a valid DiskObject,
  256.                     * windowclass will try to use env:sys/def_window.info or the default
  257.                     * project icon.
  258.                     */
  259.                 
  260.                    WINDOW_ICON, GetDiskObject( 'LayoutExample' ),
  261.                    WINDOW_ICONTITLE, 'ClassAct Example',
  262.             
  263.                    /* Below is the layout of the window 
  264.                     */
  265.             
  266.                    WINDOW_PARENTGROUP, mainlayout := VGroupObject,
  267.                       LAYOUT_SPACEOUTER, TRUE,
  268.                       LAYOUT_BEVELSTYLE, BVS_THIN,
  269.  
  270.                       /* this tag instructs layout.gadget to defer GM_LAYOUT and GM_RENDER and ask
  271.                        * the windowclass to do them. This lessens the load on input.device 
  272.                        */
  273.  
  274.                       LAYOUT_DEFERLAYOUT, Not(arguments[A_NODEFER]),
  275.  
  276.                       /* A 1-of-n chooser using the labels list we made from the label array earlier 
  277.                        */
  278.  
  279.                       StartMember, g_objtype := ChooserObject,
  280.                          CHOOSER_LABELS, typelist,
  281.                       EndMember,
  282.                       MemberLabel('_Object Type'),
  283.  
  284.                       /* Objects can be given arbitary weights within groups, and layout.gadget
  285.                        * will distribute space relative to the total weight of the group.
  286.                        * Here we set the button column to 0 weight which means minimum space.
  287.                        * Thus the listview gets all available extra space.
  288.                        */
  289.                     
  290.                       StartHGroup, BAligned,
  291.  
  292.                          StartMember, g_objlist := ListBrowserObject,
  293.                             LISTBROWSER_LABELS, objlist,
  294.                             LISTBROWSER_SHOWSELECTED, TRUE,
  295.                           EndMember,
  296.  
  297.                           StartVGroup,
  298.                              StartMember, g_top := DButton('Top'),
  299.                              StartMember, g_up := DButton('Up'),
  300.                              StartMember, g_down := DButton('Down'),
  301.                              StartMember, g_bottom := DButton('Bottom'),
  302.                              StartMember, g_sort := Button('So_rt'),
  303.                           EndGroup,
  304.                           CHILD_WEIGHTEDWIDTH, 0,
  305.  
  306.                           /* One way to keep the buttons constant size is to set the
  307.                            * group to stay at minimum size with a weight of 0. We could
  308.                            * also set the weight of each of the buttons to 0. That way
  309.                            * extra space would be distributed between the buttons
  310.                            * instead of all below. This looks better.
  311.                            */
  312.                         
  313.                            CHILD_WEIGHTEDHEIGHT, 0,
  314.                         EndGroup,
  315.                 
  316.                         /* two rows of buttons. EvenSized instructs layout.gadget that it
  317.                          * should make sure the minimum size of each matches, so that we
  318.                          * get four neat columns.
  319.                          * Again the weight is set to 0. When the window is resized, all
  320.                          * space is given to the listview.
  321.                          */
  322.                 
  323.  
  324.                          StartHGroup, EvenSized,
  325.                             StartMember, g_new := Button('_New...'),
  326.                             StartMember, g_edit := DButton('_Edit...'),
  327.                             StartMember, g_copy := DButton('Co_py'),
  328.                             StartMember, g_remove := DButton('Remove'),
  329.                          EndGroup,
  330.                          CHILD_WEIGHTEDHEIGHT, 0,
  331.             
  332.                          StartHGroup, EvenSized,
  333.                          StartMember, g_save := Button('_Save'),
  334.                          StartMember, g_use := Button('_Use'),
  335.                          StartMember, g_test := Button('_Test'),
  336.                          StartMember, g_cancel := Button('_Cancel'),
  337.                       EndGroup,
  338.                       CHILD_WEIGHTEDHEIGHT, 0,
  339.  
  340.  
  341.                       StartMember, g_help := ButtonObject,
  342.                          GA_READONLY, TRUE,
  343.                          GA_TEXT, 'Welcome to ClassAct demo!',
  344.                       EndMember,
  345.                       CHILD_WEIGHTEDHEIGHT, 0,
  346.  
  347.                    EndGroup,
  348.                 EndWindow
  349.  
  350.       IF window
  351.  
  352.          /* Finish the gadgetarray initialisation. Set gadget IDs and release verify. 
  353.           * This is one way of avoiding boring repetition in the layout description
  354.           * taglist itself.
  355.           */
  356.  
  357. -> Let's also generate the array of gadget pointers.  We couldn't generate it
  358. -> while we created gadgets because some bug (?) in EC prevents the use of
  359. -> an array in the middle of a list.
  360. -> Fortunately, it's a breeze to do using E lists.
  361.  
  362.          gl:=[NIL,
  363.               g_objtype,
  364.               g_objlist,
  365.               g_top,
  366.               g_up,
  367.               g_down,
  368.               g_bottom,
  369.               g_sort,
  370.               g_new,
  371.               g_edit,
  372.               g_copy,
  373.               g_remove,
  374.               g_help,
  375.               g_save,
  376.               g_use,
  377.               g_test,
  378.               g_cancel,
  379.               NIL]
  380.  
  381.          i:=1
  382.  
  383.          REPEAT
  384.             SetAttrsA(gl[i], [GA_ID, i, GA_RELVERIFY, TRUE, TAG_END])
  385.             INC i
  386.          UNTIL (i = G_END)
  387.  
  388.          IF (win := CA_OpenWindow(window))
  389.             asig := Shl(1,appport.sigbit)
  390.  
  391.             /* Now that the window has been opened, we can get the signal mask
  392.              * of its user port. If the program supported iconification and didn't
  393.              * use a shared IDCMP port between all windows, this signal bit
  394.              * would have to be re-queried before each Wait().
  395.              */
  396.                 
  397.             GetAttr( WINDOW_SIGMASK, window, {wsig} )
  398.     
  399.             WHILE (done = FALSE)
  400.                sig := Wait(wsig OR asig OR SIGBREAKF_CTRL_C)
  401.  
  402.                IF (sig AND (wsig OR asig))
  403.  
  404.                   /* Messages waiting at the window's IDCMP port. Loop at WM_HANDLEINPUT
  405.                    * until all have been processed.
  406.                    */
  407.  
  408.                   WHILE ((result := CA_HandleInput(window,{code})) <> WMHI_LASTMSG)
  409.  
  410.                     /* The return code of this method is two-part. The upper word describes the
  411.                      * class of the message (gadgetup, menupick, closewindow, iconify, etc),
  412.                      * and the lower word is a class-defined ID, currently in use in the
  413.                      * gadgetup and menupick return codes.
  414.                      * Switch on the class, then on the ID.
  415.                      */
  416.                         
  417.                      tmp := (result AND WMHI_CLASSMASK)
  418.  
  419.                      SELECT tmp
  420.  
  421.                         CASE WMHI_GADGETUP
  422.                              /* OK, got a gadgetup from something. Lets find out what the something is.
  423.                               * The code WORD to which a pointer was passed to WM_HANDLEINPUT has been
  424.                               * set to the Code value from the IDCMP_GADGETUP, in case we need it.
  425.                               */
  426.                             
  427.                              tmp2 := (result AND WMHI_GADGETMASK)
  428.                              SELECT tmp2
  429.  
  430.                                 CASE G_OBJLIST
  431.                                      /* User clicked on the listview 
  432.                                       */
  433.                                      IF (code = Not(0)) THEN dis := TRUE /* no node was selected */
  434.  
  435.                                      i := 0
  436.                                      REPEAT
  437.                                         SetGadgetAttrsA( gl[ids[i]], win, NIL, [GA_DISABLED, dis, TAG_END])
  438.                                         RefreshGList( gl[ids[i]], win, NIL, 1 )
  439.                                         INC i
  440.                                      UNTIL (ids[i] = G_END)
  441.                              ENDSELECT
  442.                     
  443.                         CASE WMHI_GADGETHELP
  444.  
  445.                              /* A gadget help message informs the application about the gadget
  446.                               * under the mouse pointer. The code WORD is set to the value the
  447.                               * gadget returned. Result code contains the ID of the gadget, 
  448.                               * or NULL (not in the window) or WMHI_GADGETMASK (not over a gadget).
  449.                               */
  450.                                 
  451.                              tmp3 := (result AND WMHI_GADGETMASK)
  452.                              SELECT tmp3
  453.  
  454.                                 CASE G_OBJTYPE ; StrCopy(helptext,'Choose object type')
  455.                                 CASE G_OBJLIST ; StrCopy(helptext,'Choose object to modify')
  456.                                 CASE G_TOP     ; StrCopy(helptext,'Move object to top')
  457.                                 CASE G_UP      ; StrCopy(helptext,'Move object upwards')
  458.                                 CASE G_DOWN    ; StrCopy(helptext,'Move object downwards')
  459.                                 CASE G_BOTTOM  ; StrCopy(helptext,'Move object to bottom')
  460.                                 CASE G_SORT    ; StrCopy(helptext,'Sort object list')
  461.                                 CASE G_NEW     ; StrCopy(helptext,'Create new object')
  462.                                 CASE G_EDIT    ; StrCopy(helptext,'Edit object')
  463.                                 CASE G_COPY    ; StrCopy(helptext,'Make a new copy of object')
  464.                                 CASE G_REMOVE  ; StrCopy(helptext,'Delete the object')
  465.                                 CASE G_HELP    ; StrCopy(helptext,'Hey there ;)')
  466.                                 CASE G_SAVE    ; StrCopy(helptext,'Save settings')
  467.                                 CASE G_USE     ; StrCopy(helptext,'Use these settings')
  468.                                 CASE G_TEST    ; StrCopy(helptext,'Test these settings')
  469.                                 CASE G_CANCEL  ; StrCopy(helptext,'Cancel changes')
  470.                                 DEFAULT        ; StrCopy(helptext,'')
  471.                              ENDSELECT
  472.  
  473.                              IF (SetGadgetAttrsA(gl[G_HELP], win, NIL, [GA_TEXT, helptext, TAG_END] )) THEN RefreshGList(gl[G_HELP], win, NIL, 1)
  474.  
  475.                         CASE WMHI_CLOSEWINDOW
  476.                              /* The window close gadget was hit. Time to die...
  477.                               */
  478.                              done := TRUE
  479.  
  480.                         CASE WMHI_ICONIFY
  481.                              /* Window requests that it be iconified. Handle this event as
  482.                               * soon as possible. The window is not iconified automatically to
  483.                               * give you a chance to make note that the window pointer will be 
  484.                               * invalid before the window closes. It also allows you to free
  485.                               * resources only needed when the window is open, if you wish to.
  486.                               */
  487.                              IF (CA_Iconify( window )) THEN win := NIL
  488.                                  
  489.                         CASE WMHI_UNICONIFY
  490.                              /* The window should be reopened. If you had free'd something
  491.                               * on iconify, now is the time to re-allocate it, before calling
  492.                               * CA_OpenWindow.
  493.                               */
  494.                              win := CA_OpenWindow( window )
  495.  
  496.                      ENDSELECT
  497.                   ENDWHILE
  498.  
  499.                ELSEIF (sig AND SIGBREAKF_CTRL_C)
  500.                   done := TRUE
  501.                ENDIF
  502.  
  503.             ENDWHILE
  504.  
  505.             /* Close the window and dispose of all attached gadgets 
  506.              */
  507.             DisposeObject( window )
  508.          ENDIF
  509.       ENDIF
  510.    ENDIF
  511.  
  512.    IF appport THEN DeleteMsgPort(appport)
  513.  
  514.    /* NIL is valid input for these helper functions, so no need to check.
  515.     */
  516.    freeChooserLabels( typelist )
  517.    freeBrowserNodes( objlist )
  518.  
  519.    FreeArgs(args)
  520. ENDIF
  521.  
  522. EXCEPT DO
  523.  
  524.    IF buttonbase THEN CloseLibrary(buttonbase)
  525.    IF listbrowserbase THEN CloseLibrary(listbrowserbase)
  526.    IF chooserbase THEN CloseLibrary(chooserbase)
  527.    IF windowbase THEN CloseLibrary(windowbase)
  528.    IF layoutbase THEN CloseLibrary(layoutbase)
  529.    IF labelbase THEN CloseLibrary(labelbase)
  530.    IF iconbase THEN CloseLibrary(iconbase)
  531. ENDPROC
  532.